package ltd.smallwang.web;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.cola.dto.PageResponse;
import com.alibaba.cola.dto.Response;
import com.alibaba.cola.dto.SingleResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import ltd.smallwang.client.task.api.TaskService;
import ltd.smallwang.client.task.dto.TaskAddCmd;
import ltd.smallwang.client.task.dto.TaskCategoryAddCmd;
import ltd.smallwang.client.task.dto.TaskCategoryDto;
import ltd.smallwang.client.task.dto.TaskCategoryUpdateCmd;
import ltd.smallwang.client.task.dto.TaskCompleteChangeCmd;
import ltd.smallwang.client.task.dto.TaskDeleteCmd;
import ltd.smallwang.client.task.dto.TaskDto;
import ltd.smallwang.client.task.dto.TaskExecuteRecordAddCmd;
import ltd.smallwang.client.task.dto.TaskExecuteRecordDto;
import ltd.smallwang.client.task.dto.TaskExecuteRecordQry;
import ltd.smallwang.client.task.dto.TaskQry;
import ltd.smallwang.client.task.dto.TaskUpdateCmd;
import ltd.smallwang.domain.task.Task;
import ltd.smallwang.domain.task.gateway.TaskGateway;
import ltd.smallwang.infrastructure.task.db.TaskMapper;
import ltd.smallwang.infrastructure.task.db.model.TaskPo;
import ltd.smallwang.web.convert.TaskConvert;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * 任务微服务
 *
 * @author justd
 */
@RestController
@RequestMapping("/task")
@RequiredArgsConstructor
@Slf4j
@SaCheckLogin
public class TaskController {

  private final TaskGateway taskGateway;

  private final TaskMapper taskMapper;

  private final TaskService taskService;

  /**
   * 查询任务列表
   *
   * @param pageIndex the page index
   * @param pageSize  the page size
   * @return the tasks
   */
  @GetMapping(value = "/v1/getTasks", produces = MediaType.APPLICATION_JSON_VALUE)
  public PageResponse<TaskDto> getTasks(@RequestParam("pageIndex") int pageIndex,
      @RequestParam("pageSize") int pageSize) {
    log.info("begin to get tasks");
    Long userId = StpUtil.getLoginIdAsLong();
    QueryWrapper<TaskPo> queryWrapper = new QueryWrapper<>();
    queryWrapper.lambda().eq(TaskPo::getUserId, userId);
    Long count = taskMapper.selectCount(queryWrapper);
    if (count == 0) {
      return PageResponse.of(new ArrayList<>(), 0, pageSize, pageIndex);
    }
    List<Task> taskList = taskGateway.list(userId, pageIndex, pageSize);
    List<TaskDto> taskVos = taskList.stream().map(TaskConvert.INSTANCE::convert).toList();
    return PageResponse.of(taskVos, count.intValue(), pageSize, pageIndex);
  }

  /**
   * 获取任务列表，动态条件查询
   *
   * @param taskQry the task qry
   * @return the tasks v 2
   */
  @PostMapping(value = "/v2/getTasks", produces = MediaType.APPLICATION_JSON_VALUE,
      consumes = MediaType.APPLICATION_JSON_VALUE)
  public SingleResponse<List<TaskDto>> getTasksV2(@RequestBody @Validated TaskQry taskQry) {
    return SingleResponse.of(taskService.queryTasks(taskQry));
  }

  /**
   * 创建任务
   *
   * @param taskAddCmd the task add cmd
   * @return the response
   */
  @PostMapping(value = "/v1/createTask", produces = MediaType.APPLICATION_JSON_VALUE,
      consumes = MediaType.APPLICATION_JSON_VALUE)
  public Response createTask(@RequestBody @Validated TaskAddCmd taskAddCmd) {
    log.info("begin to create task");
    taskService.createTask(taskAddCmd);
    return Response.buildSuccess();
  }

  /**
   * 提交任务完成标志变更请求
   *
   * @param taskCompleteChangeCmd 任务完成标志变更命令，包含需要变更的任务信息和新的完成标志。 必须是一个验证过的对象，确保数据的完整性和正确性。
   * @return 返回一个响应对象，如果变更操作成功，则返回成功的状态和相关数据。
   */
  @PostMapping(value = "/v1/taskCompleteFlagChange", produces = MediaType.APPLICATION_JSON_VALUE,
      consumes = MediaType.APPLICATION_JSON_VALUE)
  public Response taskCompleteFlagChange(
      @RequestBody @Validated TaskCompleteChangeCmd taskCompleteChangeCmd) {
    log.info("begin to change complete flag");
    taskService.taskCompleteChange(taskCompleteChangeCmd);
    return Response.buildSuccess();
  }

  /**
   * 批量删除任务的接口。
   *
   * @param taskDeleteCmd 包含需要删除的任务ID列表的命令对象。
   * @return 返回操作结果，如果成功则返回成功的响应。
   */
  @PostMapping(value = "v1/batchDeleteTask", produces = MediaType.APPLICATION_JSON_VALUE,
      consumes = MediaType.APPLICATION_JSON_VALUE)
  public Response batchDeleteTask(@RequestBody TaskDeleteCmd taskDeleteCmd) {
    log.info("begin to batch delete task");
    taskService.deleteTask(taskDeleteCmd.getIdList());
    return Response.buildSuccess();
  }

  /**
   * 保存执行记录 该接口用于接收客户端发送的执行记录添加命令，然后将其保存到数据库中。
   *
   * @param taskExecuteRecordAddCmd 客户端发送的任务执行记录添加命令，包含执行记录的详细信息。该参数通过RequestBody接收，确保了数据的JSON格式。
   * @return 返回操作结果，如果保存成功，则返回一个成功的响应对象。
   */
  @PostMapping(value = "v1/saveExecuteRecord", produces = MediaType.APPLICATION_JSON_VALUE,
      consumes = MediaType.APPLICATION_JSON_VALUE)
  public Response saveExecuteRecord(
      @RequestBody @Validated TaskExecuteRecordAddCmd taskExecuteRecordAddCmd) {
    taskService.saveExecuteRecord(taskExecuteRecordAddCmd);
    return Response.buildSuccess();
  }

  /**
   * 提供获取任务执行记录的功能接口。 通过接收客户端发送的JSON格式的查询请求，返回一个包含任务执行记录的列表。
   *
   * @param taskExecuteRecordQry 任务执行记录查询参数，是一个经过验证的请求体对象，用于指定查询条件。
   * @return 返回一个封装了任务执行记录列表的SingleResponse对象，响应为JSON格式。
   */
  @PostMapping(value = "v1/getTaskExecuteRecords", produces = MediaType.APPLICATION_JSON_VALUE,
      consumes = MediaType.APPLICATION_JSON_VALUE)
  public SingleResponse<List<TaskExecuteRecordDto>> getTaskExecuteRecords(
      @RequestBody @Validated TaskExecuteRecordQry taskExecuteRecordQry) {
    return SingleResponse.of(taskService.queryTaskExecuteRecords(taskExecuteRecordQry));
  }

  /**
   * 更新任务的API接口。
   *
   * @param taskUpdateCmd 包含任务更新信息的命令对象，必须是有效的请求体。
   * @return 返回一个表示操作成功与否的响应对象。
   */
  @PostMapping(value = "v1/updateTask", produces = MediaType.APPLICATION_JSON_VALUE,
      consumes = MediaType.APPLICATION_JSON_VALUE)
  public Response updateTask(@RequestBody @Validated TaskUpdateCmd taskUpdateCmd) {
    taskService.updateTask(taskUpdateCmd);
    return Response.buildSuccess();
  }

  /**
   * 根据任务ID获取任务详情。
   *
   * @param id 任务的唯一标识符。
   * @return 返回一个包含任务详情的SingleResponse对象，其中包含了任务的DTO（数据传输对象）。
   */
  @GetMapping(value = "v1/getTask", produces = MediaType.APPLICATION_JSON_VALUE)
  public SingleResponse<TaskDto> getTask(@RequestParam("id") Long id) {
    return SingleResponse.of(taskService.getTask(id));
  }

  /**
   * 通过GET请求获取任务分类列表。
   *
   * 此方法定义了一个GET请求的处理方法，用于查询任务分类。它通过生产JSON格式的响应来满足客户端的需求。
   * 请求的URL路径为"v1/queryTaskCategories"，响应的MIME类型为"application/json"。
   *
   * @return SingleResponse<List < TaskCategoryDto>> 包含任务分类列表的响应。响应体是一个TaskCategoryDto对象的列表，
   * TaskCategoryDto封装了任务分类的相关信息。SingleResponse用于包装响应数据，同时可以携带额外的响应状态和消息。
   */
  @GetMapping(value = "v1/queryTaskCategories", produces = MediaType.APPLICATION_JSON_VALUE)
  public SingleResponse<List<TaskCategoryDto>> queryTaskCategories() {
    return SingleResponse.of(taskService.queryTaskCategories());
  }

  /**
   * 批量删除任务分类。 该接口通过接收一个包含任务分类ID的列表，批量删除相应的任务分类。
   * <p>
   * 请求方法: POST 请求路径: v1/batchDeleteTaskCategories 请求内容类型: application/json 响应内容类型:
   * application/json
   * <p>
   * 请求参数: - @RequestBody List<Long> idList: 需要删除的任务分类ID列表。
   * <p>
   * 返回结果: - 如果删除成功，返回一个表示成功的响应。
   *
   * @param idList 任务分类ID列表，用于指定需要删除的任务分类。
   * @return 表示操作结果的响应对象。
   */
  @PostMapping(value = "v1/batchDeleteTaskCategories", produces = MediaType.APPLICATION_JSON_VALUE,
      consumes = MediaType.APPLICATION_JSON_VALUE)
  public Response batchDeleteTaskCategories(@RequestBody List<Long> idList) {
    taskService.batchDeleteTaskCategories(idList);
    return Response.buildSuccess();
  }

  /**
   * 更新任务分类的接口。
   *
   * 通过POST请求调用此接口，使用JSON格式传输数据，更新任务分类的信息。 请求体中包含需要更新的任务分类信息，由TaskCategoryUpdateCmd对象表示。
   *
   * @param taskCategoryUpdateCmd 包含任务分类更新信息的命令对象，需要进行有效性验证。
   * @return 返回操作结果，如果操作成功，则返回一个包含成功信息的Response对象。
   */
  @PostMapping(value = "v1/updateTaskCategory", produces = MediaType.APPLICATION_JSON_VALUE,
      consumes = MediaType.APPLICATION_JSON_VALUE)
  public Response updateTaskCategory(
      @RequestBody @Validated TaskCategoryUpdateCmd taskCategoryUpdateCmd) {
    taskService.updateTaskCategory(taskCategoryUpdateCmd);
    return Response.buildSuccess();
  }

  /**
   * 创建任务分类
   *
   * 通过接收TaskCategoryAddCmd命令对象，创建一个新的任务分类。 此方法说明了如何将来自客户端的JSON数据转换为服务器端使用的命令对象，
   * 并进一步如何将该命令对象处理（即创建任务分类）以及如何响应客户端。
   *
   * @param taskCategoryAddCmd 包含新任务分类信息的命令对象。
   * @return 成功创建任务分类后的响应对象。
   */
  @PostMapping(value = "v1/createTaskCategory", produces = MediaType.APPLICATION_JSON_VALUE,
      consumes = MediaType.APPLICATION_JSON_VALUE)
  public Response createTaskCategory(@RequestBody @Validated TaskCategoryAddCmd taskCategoryAddCmd) {
    taskService.insertTaskCategory(taskCategoryAddCmd);
    return Response.buildSuccess();
  }
}
